import yaml
import platform

import distro
from lxml import etree

from InstallDbForCentOS import InstallDbForCentOS
from InstallDbForEuler import InstallDbForEuler
from InstallDbForKylin import InstallDbForKylin
from InstallDbForUos import InstallDbForUos
from InstallDbInterface import InstallDbInterface
from Utils import Utils


def get_yml_config_data():
    with open('config.yml', 'r', encoding='utf-8') as f:
        try:
            return yaml.safe_load(f)
        except yaml.YAMLError as exc:
            print("read config yml file error: ", exc)


def get_system_info():
    system = 'unknow'
    env = {}
    cpu_arch = platform.machine().lower()
    if cpu_arch.find("x86_64") < 0:
        cpu_arch = "aarch64"
    env["cpu_arch"] = cpu_arch
    distro_info = distro.info()
    distro_id = distro_info.get('id').lower()
    if 'centos' in distro_id:
        system = 'centos'
    elif 'euler' in distro_id or 'euleros' in distro_id:
        system = 'euler'
    elif 'kylin' in distro_id:
        system = 'kylin'
    elif 'uos' in distro_id:
        system = 'uos'
    return system, env


env_router_rules = {"centos": InstallDbForCentOS,
                    "euler": InstallDbForEuler,
                    "kylin": InstallDbForKylin,
                    "uos": InstallDbForUos}


def get_xml_info(type):
    if type == 'stand-alone':
        ret, msg = Utils.check_file_exist("cluster_config_standalone.xml", None)
        if ret is False:
            return False, "can not find cluster_config_standalone.xml",None
        return True, 'success', etree.parse("cluster_config_standalone.xml")
    else:
        ret, msg = Utils.check_file_exist("cluster_config_cluster.xml", None)
        if ret is False:
            return False, "can not find cluster_config_cluster.xml", None
        return True, 'success', etree.parse("cluster_config_cluster.xml")

def config_params_check(config):
    if config['user'] == '':
        return False, 'user is empty.'
    if config['userGroup'] == '':
        return False, 'userGroup is empty.'
    if config['installPath'] == '':
        return False, 'installPath is empty.'
    if config['dbPath'] == '':
        return False, 'dbPath is empty.'
    if config['packageName'] == '':
        return False, 'packageName is empty.'
    if config['packageOmName'] == '':
        return False, 'packageOmName is empty.'
    if config['currentNode'] == '':
        return False, 'currentNode is empty.'
    if config['currentIp'] == '':
        return False, 'currentIp is empty.'
    if config['nodes'] == '':
        return False, 'nodes is empty.'
    if config['userPasswd'] == '':
        return False, 'userPasswd is empty.'
    if config['deploymentType'] == '':
        return False, 'deploymentType is empty. please select "stand-alone" or "cluster"'
    if config['deploymentType'] != 'stand-alone' and config['deploymentType'] != 'cluster':
        return False, 'deploymentType is error. please select "stand-alone" or "cluster"'
    if config['dataNode1'] == '':
        return False, 'dataNode1 is empty.'
    if config['max_process_memory'] == '':
        return False, 'max_process_memory is empty, at least 2GB'
    if config['shared_buffers'] == '':
        return False, 'shared_buffers is empty, at least 128MB'
    if config['bulk_write_ring_size'] == '':
        return False, 'bulk_write_ring_size is empty, at least 128MB'
    if config['cstore_buffers'] == '':
        return False, 'cstore_buffers is empty, at least 16MB'
    return True, 'success'


def main():
    # 1. read config file
    config_data = get_yml_config_data()
    Utils.print_title('config info')
    Utils.print_config(config_data)
    ret, msg = config_params_check(config_data)
    if ret is not True:
        print("- config params check failed, err msg {}.".format(msg))
        return False, msg
    ret, msg, xml_tree = get_xml_info(config_data['deploymentType'])
    if ret is False:
        print("- " + msg)
        return -1
    # 2. get system info
    system_info, env = get_system_info()
    if system_info not in env_router_rules:
        print("- can not get system info.")
        return -1
    plugin = env_router_rules[system_info]
    Utils.print_title('system info')
    print("- cpu arch: {} os: {}.".format(env['cpu_arch'], system_info))
    ins: InstallDbInterface = plugin(config_data, xml_tree, env)
    # 3. preinstall with root
    if str(Utils.get_current_user()).find('root') >= 0:
        Utils.print_title("preinstall")
        preinstall_result, msg = ins.preinstall()
        Utils.print_title('exec result')
        if preinstall_result is not True:
            print("- preinstall failed, err msg {}.".format(msg))
            return -2, msg

        # 4. check env before install
        Utils.print_title("precheck")
        precheck_result, msg = ins.precheck()
        if precheck_result is not True:
            print("- precheck fail,the environment does not meet the requirements: ", msg)
        else:
            print("- precheck success, change user to {} and execute this script again.".format(config_data['user']))
        return 0

    # 5. start to install issedb
    Utils.print_title("install")
    install_result, install_msg = ins.install()
    if install_result is not True:
        print("install err : ", install_msg)
        return -3
    # # 6. process after install
    # after_install_result, after_install_msg = ins.after_install()
    # if after_install_result is not True:
    #     print("the environment does not meet the requirements: ", after_install_msg)
    #     return -4


if __name__ == "__main__":
    main()
